package com.wqy.netty.codc;

import com.wqy.netty.ConstantValue.ConstantValue;
import com.wqy.netty.model.Request;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.frame.FrameDecoder;

/**
 * @Auther: WangQingyang
 * @Date: 2020/3/31 14:52
 * @Description: 请求解码器
 *  * <pre>
 *  * 数据包格式
 *  * +——----——+——-----——+——----——+——----——+——-----——+
 *  * | 包头	| 模块号  | 命令号 |  长度  |   数据  |
 *  * +——----——+——-----——+——----——+——----——+——-----——+
 *  * </pre>
 *  * 包头4字节
 *  * 模块号2字节short
 *  * 命令号2字节short
 *  * 长度4字节(描述数据部分字节长度)
 *  *
 *  协助解决粘包问题
 */
public class RequestDecoder extends FrameDecoder {
    /**
     * 基本数据包长度
     */
    public static int BASE_LENGTH = 4+2+2+4;
    @Override
    protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
        //可读长度必须大于基本长度
        if (buffer.readableBytes() >= BASE_LENGTH){
            //防止socket攻击
            if (buffer.readableBytes()>2048){//超长后截掉
                buffer.skipBytes(buffer.readableBytes());
            }

            //记录包头开始的读指针的位置
            int beginReader;
            while (true) {
                beginReader  = buffer.readerIndex();
                buffer.markReaderIndex();
                if (buffer.readInt() == ConstantValue.FLAG){
                    break;
                }
                //未读到包头，略过一个字节
                buffer.resetReaderIndex();
                buffer.readByte();
                // 略过一个字节后，长度变的不满足
                if (buffer.readableBytes() < BASE_LENGTH){
                    return null;
                }
            }
            //模块号
            short module = buffer.readShort();
            //命令号
            short cmd = buffer.readShort();
            //长度
            int datalength = buffer.readInt();
            //如果读到的数据小于数据长度，就要继续读
            if (buffer.readableBytes() < datalength){
                buffer.readerIndex(beginReader);
                return null;
            }
            byte[]  data = new byte[datalength];
            buffer.readBytes(data);
            Request request = new Request();
            request.setModule(module);
            request.setCmd(cmd);
            request.setData(data);
            //继续往下传递，
            return request;
        }
        //数据包不完整，需要等待后面的包来
        return null;
    }
}
